# -- coding: utf-8 --
# @time : 2023/7/13
# @author : 周梦泽
# @file : traffics_source.py
# @software: pycharm
# 商品单品分析/流量来源分析
import datetime
import time
import traceback
from datetime import timedelta

import backoff
import pandas as pd
import requests
from DrissionPage import WebPage
from DrissionPage.action_chains import ActionChains
from DrissionPage.commons.keys import Keys

from autoTask.operaitonAid.utils.taobao_requests_headers import page_headers
from autoTask.taobao.redis_key_mange import RedisKey
from autoTask.taobao.sycm.utils.selectDays import select_days
from autoTask.taobao.taobao_login import Login
from common.logger.log import log_
from common.redis import redis_client
from common.utils import DateUtil
from common.utils.calculate_date import count_day
from common.utils.web_page_util import MockTap, random_delay, Tap


class ProductSingleAnalysis:
    def __init__(self, params: dict):
        self.account = params["account"]
        self.password = params["password"]
        self.source_of_traffic = params["sourceOfTraffic"]
        self.data_cycle = params["dataCycle"]
        self.open_box = True

    @staticmethod
    def requests_api(page, target_date: str, data_cycle: int):
        page_num = 1
        goods_itemid_list = []
        date_before = str(count_day(target_date, -data_cycle))
        while True:
            headers = page_headers(page)
            params = {
                'dateRange': f'{date_before}|{target_date}',
                'dateType': f'recent{data_cycle}',
                'pageSize': '10',
                'page': page_num,
                'order': 'desc',
                'orderBy': 'payAmt',
                'device': '0',
                'compareType': 'cycle',
                'follow': 'false',
                'keyword': '',
                'cateId': '',
                'cateLevel': '',
                'indexCode': 'payAmt,payItmCnt,sucRefundAmt,itemCartCnt,itmUv',
            }
            goods_response = requests.get(url="https://sycm.taobao.com/cc/item/view/top.json", headers=headers,
                                          params=params)
            log_.info(f"请求到的商品数据:{goods_response.json()}")
            record_count = goods_response.json()["data"]["recordCount"]
            log_.info(f"获取到商品总数：{record_count}")

            for goods in goods_response.json()["data"]["data"]:
                goods_itemid_list.append(goods["itemId"]["value"])
            if page_num >= record_count / 10:
                break
            page_num += 1
            random_delay((3, 6))
        log_.info(f"商品itemid列表：{goods_itemid_list}")
        return goods_itemid_list

    @backoff.on_exception(backoff.constant, Exception, max_tries=3,
                          interval=5, on_backoff=lambda details: log_.error(traceback.format_exc()))
    def browsing_source(self, page: WebPage, itemid: str, source: str, data_cycle: int):
        page.get(f"https://sycm.taobao.com/cc/item_archives?activeKey=flow&itemId={itemid}")
        page.wait.load_complete(timeout=30)
        select_days(page, data_cycle)
        effect_time_box = page(
            "x://div[@class='sycm-flow-item-source-attr-selector']//div[@class='ant-select-selection-selected-value']")
        # if self.open_box:
        if self.open_box and source != effect_time_box.text:
            log_.info(f"点击转化效果归属于{source}")
            MockTap(effect_time_box, msg="点击转化效果归属于失败", before_delay=(2, 4))()
            if page("x://div[contains(@class, 'ant-select-open')]"):
                # 如果能打开下拉框
                log_.info("可以打开下拉框")
                # self.open_box = True
                MockTap(page("x://ul[@role='listbox']")(f"tx:{source}"), before_delay=(1, 3), reduce_scope=(3, 5))()
                # 点击下拉框中的对应选项
            else:
                log_.info("不能打开下拉框, 改变访问来源为每一次访问来源")
                self.source_of_traffic = "每一次访问来源"
                self.open_box = False

    @staticmethod
    @backoff.on_exception(backoff.constant, Exception, max_tries=3,
                          interval=5, on_backoff=lambda details: log_.error(traceback.format_exc()))
    def aming_search_page(page: WebPage):
        """"
        阿明查查页面
        """
        page("x://div[@class='Product360TrafficSourceNew_btn_group']")("tx:一键转化").click(by_js=True)
        copy_mode = page("x://div[@class='tip-wrap']//span/span").text
        if "模式二" not in copy_mode:
            log_.warning("复制模式不是模式二, 正在修改")
            page("x://div[@class='copy-btn-wrap']//button[contains(@class, 'el-dropdown__caret-button')]/span").hover()
            Tap(page("x:/html/body/ul[contains(@class, 'el-dropdown-menu--small')]//li[2]/div/button"), by_js=True,
                msg="点击默认按钮失败")()
        Tap(page("x://div[@class='tip-wrap']//span/span"), msg="点击复制按钮失败", by_js=True, before_delay=(2, 4))()
        time.sleep(3)
        ActionChains(page).key_down(Keys.ESCAPE)
        df = pd.read_clipboard()
        return df

    @staticmethod
    def build_key(store_name: str, source_of_traffic: str, data_cycle: str):
        key_prefix = RedisKey.sycm.llly.key
        key = key_prefix + f"{store_name}:{source_of_traffic}:{data_cycle}天"
        return key

    @staticmethod
    def data_processing(df_list: list[pd.DataFrame], key: str):
        """
        数据处理, 合并数据, 去除重复表头, 去除空行
        :param key: redis key
        :param df_list: 数据列表
        :return:
        """
        df = pd.concat(df_list).reset_index(drop=True)  # 合并数据, 重置索引
        df = df.dropna(how='all')  # 去除空行
        df = df.drop(df[df.isin(['商品id']).any(axis=1)].index)  # 去除重复表头
        # 去除%号将百分比转化为小数
        df = df.applymap(
            lambda x: round(float(x.strip('%')) / 100, 2) if isinstance(x, str) and x.endswith('%') else x)
        # 去除逗号
        df = df.applymap(lambda x: x.replace(',', '') if isinstance(x, str) and ',' in x else x)

        log_.info("更新缓存")
        # df.to_excel("测试1.xlsx", index=False)
        # print(key)
        redis_client.put(key, df.to_json(orient='records', force_ascii=False), ex=DateUtil.seconds_until_end_of_day(1))
        return df

    def __call__(self):
        page, store_name = Login(self.account, self.password).execute(
            url="https://sycm.taobao.com/portal/home.htm")
        key = self.build_key(store_name, self.source_of_traffic, self.data_cycle)
        df_json = redis_client.get(key, type_=str)
        if df_json:
            # df = pd.read_json(df_json)
            log_.info(f"从redis中获取到数据:{key}")
            # df.to_excel("测试2.xlsx", index=False)
            # df_json = df.to_json(orient='records', force_ascii=False)
            # print(df_json)
            return df_json, store_name
        elif df_json is None and self.source_of_traffic != "每一次访问来源":
            log_.info(f"此账号目前没有:{self.source_of_traffic}权限")
            key = self.build_key(store_name, "每一次访问来源", self.data_cycle)
            df_json = redis_client.get(key, type_=str)
            if df_json:
                # df = pd.read_json(df_json)
                log_.info(f"从redis中获取到数据:{key}")
                # df.to_excel("测试3.xlsx", index=False)
                # df_json = df.to_json(orient='records', force_ascii=False)
                # print(df_json)
                return df_json, store_name
            else:
                key = self.build_key(store_name, self.source_of_traffic, self.data_cycle)
        log_.info("缓存中没有数据, 正在从浏览器获取数据 ")
        target_date = str(datetime.date.today() - timedelta(days=1))
        goods_itemid_list = self.requests_api(page, target_date=target_date, data_cycle=self.data_cycle)
        df_list = []
        for itemid in goods_itemid_list:
            random_delay((4, 7))
            self.browsing_source(page, itemid, self.source_of_traffic, self.data_cycle)
            df = self.aming_search_page(page)
            df_list.append(df)
        if len(df_list) > 0:
            df = self.data_processing(df_list, key)
            df_json = df.to_json(orient='records', force_ascii=False)
            return df_json, store_name


if __name__ == '__main__':
    param = {
        "account": "中山杰特电器:生参",
        "password": "yzt123456",
        "sourceOfTraffic": "最后一次访问来源",  # 每一次访问来源/第一次访问来源/最后一次访问来源/
        "dataCycle": 30
    }
    ProductSingleAnalysis(param)()
# https://sycm.taobao.com/cc/item_archives?activeKey=flow&itemId=643929194261
#
# https://sycm.taobao.com/cc/item/view/top.json?dateRange=2023-05-26|2023-06-24&dateType=recent30&pageSize=10&page=1&order=desc&orderBy=payAmt&device=0&compareType=cycle&keyword=&follow=false&cateId=&cateLevel=&indexCode=payAmt,payItmCnt,sucRefundAmt,itemCartCnt,itmUv
# https://sycm.taobao.com/cc/item_archives?activeKey=diagnosis&dateRange=2023-06-24%7C2023-06-24&dateType=day&itemId=643929194261
# https://sycm.taobao.com/cc/item_archives?activeKey=flow&dateRange=2023-06-24%7C2023-06-24&dateType=day&itemId=643929194261
